home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
apps
/
xconf
/
ConfDoc.c++
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
27KB
|
958 lines
/*
* Copyright 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
// Conf includefile
#include "ConfDoc.h"
// unix includes
#include <stdlib.h>
#include <sys/socket.h>
#include <malloc.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <bstring.h>
#include <CC/osfcn.h>
#include <netdb.h>
#include <arpa/inet.h>
// X11 and motif includes
#include <X11/StringDefs.h>
#include <Xm/Text.h>
#include <Xm/PushB.h>
#include <Xm/Separator.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
///////////////////////////////////////////////////////////////////////////////
// callback definitions
///////////////////////////////////////////////////////////////////////////////
void ConfDoc::quitCB(Widget, XtPointer clientData, XtPointer)
{
ConfDoc *obj = (ConfDoc *)clientData;
obj->sendMsg(LOGOUT, obj->_user, obj->_group, " ");
close(obj->_socket);
exit(1);
}
void ConfDoc::usersCB(Widget, XtPointer clientData, XtPointer)
{
ConfDoc *obj = (ConfDoc *)clientData;
obj->_userList.open();
}
void ConfDoc::groupsCB(Widget, XtPointer clientData, XtPointer)
{
ConfDoc *obj = (ConfDoc *)clientData;
obj->_groupList.open();
}
void ConfDoc::helpCB(Widget, XtPointer clientData, XtPointer)
{
ConfDoc *obj = (ConfDoc *)clientData;
obj->_helpList.open();
}
void ConfDoc::recvCB(XtPointer data, int /*sock*/, XtInputId* /*id*/)
{
ConfDoc *obj = (ConfDoc *)data;
struct Message msg, reply;
struct sockaddr_in f;
int fromlen = sizeof(f);
char buf[MAX_BUF_SIZE];
char tbuf[16];
time_t rawtime;
if(recvfrom(obj->_socket, &msg, sizeof(msg),0, &f, &fromlen) < 0) {
if(errno == EBADF)
exit(-1);
perror("recvfrom");
exit(-1);
}
// if it's an unknown group, add it to the list
if(!obj->_groupList.find(msg.group)) {
obj->_groupList.add(msg.group);
bzero(msg.data, sizeof(msg.data)); // clear send buffer
return;
}
// if it's a broadcast message, print it and return
if(msg.flags == BROADCAST) {
time(&rawtime);
cftime(tbuf, "%I:%M ", &rawtime);
strcpy(buf, "BCAST> ");
strcat(buf, tbuf);
strcat(buf, msg.data);
obj->_recvConfText->putStr(buf);
bzero(msg.data, sizeof(msg.data)); // clear send buffer
return;
}
// if it's for our group
if(obj->_groupList.findSelected(msg.group)) {
// add any unknown users
if(!obj->_userList.find(msg.user)) {
obj->_userList.add(msg.user);
}
// check the msg type, and do the right thing
switch(msg.flags) {
case MESSAGE :
time(&rawtime);
cftime(tbuf, "%I:%M ", &rawtime);
strcpy(buf, tbuf);
strcat(buf, msg.data);
obj->_recvConfText->putStr(buf);
break;
case USER :
// announce the name change
strcpy(buf, "NAME> '");
strcat(buf, msg.data);
strcat(buf, "' changed to '");
strcat(buf, msg.user);
strcat(buf, "'.");
obj->_recvConfText->putStr(buf);
// remove the old name from the user list
obj->_userList.remove(msg.data);
// if it's you, change yer name
if(!strcmp(msg.data, obj->_user))
strcpy(obj->_user, msg.user);
break;
case PRIVATE :
if(!strcmp(msg.user, obj->_user)) {
strcpy(buf, "PRIVATE> ");
strcat(buf, msg.data);
obj->_recvConfText->putStr(buf);
}
break;
case LOGIN :
// announce the new user
strcpy(buf, "LOGIN> ");
strcat(buf, msg.user);
obj->_recvConfText->putStr(buf);
// send a reply
f.sin_port = obj->_port;
reply.flags = REPLY;
strcpy(reply.user, obj->_user);
strcpy(reply.group, obj->_group);
sendto(obj->_socket, &reply, sizeof(reply), 0, &f, sizeof(f));
break;
case FIND :
// send a reply
f.sin_port = obj->_port;
reply.flags = REPLY;
strcpy(reply.user, obj->_user);
strcpy(reply.group, obj->_group);
sendto(obj->_socket, &reply, sizeof(reply), 0, &f, sizeof(f));
break;
case LOGOUT :
// announce the user's exit
strcpy(buf, "LOGOUT> ");
strcat(buf, msg.user);
obj->_recvConfText->putStr(buf);
// remove user from the user list
obj->_userList.remove(msg.user);
break;
case RING :
if(!strcmp(msg.user, obj->_user)) {
XBell(XtDisplay(obj->_recvText), 50);
strcpy(buf, "RING> ");
strcat(buf, msg.data);
obj->_recvConfText->putStr(buf);
}
break;
case URGENT :
strcpy(buf, "URGENT> ");
strcat(buf, msg.data);
obj->_recvConfText->putStr(buf, TRUE);
break;
case REPLY :
break;
default :
break;
}
}
// clear the msg buffer
bzero(msg.data, sizeof(msg.data)); // clear send buffer
}
void ConfDoc::sendCB(Widget, XtPointer clientData, XtPointer callData)
{
char buf[MAX_BUF_SIZE];
ConfDoc *obj = (ConfDoc *)clientData;
XmAnyCallbackStruct *data = (XmAnyCallbackStruct *)callData;
char *tmp = XmTextGetString(obj->_sendText);
if(strlen(tmp) > MAX_BUF_SIZE) {
obj->_recvConfText->putStr("ERROR> input too long (255 chars max).");
XtFree(tmp);
return;
}
strcpy(buf, tmp);
XtFree(tmp);
if(buf[0] == ':') {
switch (tolower(buf[1])) {
case 'b' :
obj->sendBroadcast(buf);
break;
case 'c' :
// obj->setupChannel(buf);
obj->_recvConfText->putStr("INFO> 'channel' not implemented.");
break;
case 'f' :
obj->_recvConfText->putStr("INFO> performing find.");
obj->findUser(buf);
break;
case 'g' :
obj->setGroup(buf);
break;
case 'h' :
case '?' :
obj->_helpList.open();
break;
case 'n' :
obj->setName(buf);
break;
case 'q' :
// make this think we're x doing a callback
obj->quitCB(NULL, (XtPointer)obj, NULL);
case 'p' :
case 's' :
obj->sendPrivate(buf, 0);
break;
case 'r' :
obj->sendPrivate(buf, 1);
break;
case 'u' :
obj->sendUrgent(buf);
break;
case 'v' :
obj->_recvConfText->putStr("INFO> xconf version 2.08");
break;
case 'w' :
obj->_userList.open();
break;
default :
obj->_recvConfText->putStr("ERROR> No such command.");
break;
}
}
else {
obj->sendMsg(MESSAGE, obj->_user, obj->_group, buf);
}
bzero(buf, MAX_BUF_SIZE);
// reset for the next message
XmTextSetString(obj->_sendText, "");
XmTextSetInsertionPosition(obj->_sendText, 0);
}
///////////////////////////////////////////////////////////////////////////////
// end of callback definitions
///////////////////////////////////////////////////////////////////////////////
ConfDoc::ConfDoc(XtAppContext app, const char*)
{
_app = app;
}
ConfDoc::~ConfDoc() {}
void ConfDoc::init(int port, char* server)
{
_port = port;
_server = server;
_user = (char *)malloc(30*sizeof(char)); // reserve 30 bytes for 'user'
_group = (char *)malloc(30*sizeof(char)); // reserve 30 bytes for 'group'
// JR - working on the .xconfrc stuff..
// open the .confrc file
// _rcfile.open();
// _rcfile.read();
if(!(_user = getenv("CONFUSER"))) {
if(!(_user = getenv("LOGNAME"))) {
_user = "def_user";
}
}
if(!(_group = getenv("CONFGROUP"))) {
_group = "def_group";
}
_userList.add(_user);
_groupList.add(_group, TRUE);
setInputLabel(_group);
// load the help information
_helpList.add("Commands start with a colon (:) Available commands are:");
_helpList.add("( [] denotes optional characters/fields)");
_helpList.add(" :b[roadcast] msg ---- broadcast a message to all groups.");
_helpList.add(" :c[hannel] user ----- open a private channel to 'user'.");
_helpList.add(" :f[ind] user -------- report whether 'user' is logged in.");
_helpList.add(" :g[roup] group ------ change your group to 'group'.");
_helpList.add(" :h[elp] ------------- print this help message.");
_helpList.add(" :n[ame] name -------- change your name to 'name'.");
_helpList.add(" :q[uit] ------------- quit this program.");
_helpList.add(" :r[ing] user [msg] -- ring the bell of 'user'");
_helpList.add(" :s[end] user msg ---- send a private message to 'user'.");
_helpList.add(" :u[rgent] msg ------- send an urgent message.");
_helpList.add(" :v[ersion] ---------- show xconf version number.");
_helpList.add(" :w[ho] -------------- bring up the user dialog.");
_helpList.add(" ");
if(!setupSockets()) {
exit(-1);
}
// announce that you're here
if(!sendMsg(LOGIN, _user, _group, " "))
_recvConfText->putStr("ERROR> sendMsg() failed.");
}
Boolean ConfDoc::setupSockets()
{
_addrSize = sizeof(struct sockaddr_in);
bzero(&_sendAddr, _addrSize);
_sendAddr.sin_family = AF_INET;
_sendAddr.sin_port = htons(_port);
_sendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
bzero(&_recvAddr, _addrSize);
_recvAddr.sin_family = AF_INET;
_recvAddr.sin_port = htons(_port);
_recvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(_server) {
if(!setupTCP()) {
fprintf(stderr, "Error setting up connection to %s.\n", _server);
return(FALSE);
}
}
else {
if(!setupUDP()) {
fprintf(stderr, "Error setting up multicast socket.\n");
return(FALSE);
}
}
// add the receiving socket as an input source
XtAppAddInput(_app, _socket, (XtPointer)XtInputReadMask,
(XtInputCallbackProc)&ConfDoc::recvCB, (XtPointer)this);
return(TRUE);
}
Boolean ConfDoc::setupTCP()
{
// bind to a remote machine
_socket = socket(AF_INET, SOCK_STREAM, 0);
if(_socket < 0) {
perror("socket");
return(FALSE);
}
struct hostent *hp = gethostbyname(_server);
if (hp == NULL) {
perror("gethostbyname");
return(FALSE);
}
memcpy(&_sendAddr.sin_addr, hp->h_addr, hp->h_length);
if(connect(_socket, &_sendAddr, _addrSize) < 0) {
perror("connect");
return(FALSE);
}
return(TRUE);
}
Boolean ConfDoc::setupUDP()
{
_socket = socket(AF_INET, SOCK_DGRAM, 0);
if(_socket < 0) {
perror("socket");
return(FALSE);
}
int on = 1;
// doing this before the bind allows multiple bindings to this port
if(setsockopt(_socket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
perror("setsockopt(SO_REUSEPORT)");
return(FALSE);
}
// bind to a multicast address
struct in_addr grpAddr;
grpAddr.s_addr = inet_addr(XCONF_MCAST_GROUP);
if(!IN_MULTICAST(grpAddr.s_addr)) {
fprintf(stderr, "Invalid multicast group address.\n");
return(FALSE);
}
u_char ttl = MAX_MCAST_HOPS;
int sz = sizeof(ttl);
if(setsockopt(_socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sz) < 0) {
perror("setsockopt(IP_MULTICAST_TTL)");
return(FALSE);
}
_sendAddr.sin_addr = grpAddr;
struct ip_mreq mreq;
mreq.imr_multiaddr = grpAddr;
struct in_addr ifAddr;
ifAddr.s_addr = htonl(INADDR_ANY);
mreq.imr_interface = ifAddr;
sz = sizeof(mreq);
if(setsockopt(_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sz) < 0) {
perror("setsockopt(IP_ADD_MEMBERSHIP)");
return(FALSE);
}
if(bind(_socket, &_recvAddr, _addrSize) < 0) {
perror("bind");
return(FALSE);
}
if(fcntl(_socket, F_SETFL, FASYNC) < 0) {
perror("fcntl");
return(FALSE);
}
if(fcntl(_socket, F_SETOWN, getpid()) < 0) {
perror("fcntl");
return(FALSE);
}
return(TRUE);
}
Widget ConfDoc::build(Widget parent)
{
Arg args[10]; // make sure this is large enough
// create the main form that all the subcomponents will go in
Widget form = XmCreateForm(parent, "form", NULL, 0);
XtManageChild(form);
// create the output label
int n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
Widget outputLabel = XmCreateLabel(form, "outputLabel", args, n);
XtManageChild(outputLabel);
// create a help button
n = 0;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
Widget helpButton = XmCreatePushButton(form, "helpButton", args, n);
XtManageChild(helpButton);
XtAddCallback(helpButton, XmNactivateCallback,
(XtCallbackProc)&ConfDoc::helpCB, (XtPointer)this);
// create a groups button
n = 0;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, helpButton); n++;
Widget usersButton = XmCreatePushButton(form, "usersButton", args, n);
XtManageChild(usersButton);
XtAddCallback(usersButton, XmNactivateCallback,
(XtCallbackProc)&ConfDoc::usersCB, (XtPointer)this);
// create a users button
n = 0;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, usersButton); n++;
Widget groupsButton = XmCreatePushButton(form, "groupsButton", args, n);
XtManageChild(groupsButton);
XtAddCallback(groupsButton, XmNactivateCallback,
(XtCallbackProc)&ConfDoc::groupsCB, (XtPointer)this);
// create a quit button
n = 0;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNrightWidget, groupsButton); n++;
Widget quitButton = XmCreatePushButton(form, "quitButton", args, n);
XtManageChild(quitButton);
XtAddCallback(quitButton, XmNactivateCallback,
(XtCallbackProc)&ConfDoc::quitCB, (XtPointer)this);
// create a separator between the input and command areas
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, quitButton); n++;
Widget separator = XmCreateSeparator(form, "separator", args, n);
XtManageChild(separator);
// create a frame for the text input area
n = 0;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, separator); n++;
Widget sendFrame = XmCreateFrame(form, "sendFrame", args, n);
XtManageChild(sendFrame);
// create a text input area
n = 0;
XtSetArg(args[n], XmNorientation, XmHORIZONTAL); n++;
Widget sendForm = XmCreateForm(sendFrame, "sendForm", args, n);
XtManageChild(sendForm);
// create the text input prompt
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
Widget sendPrompt = XmCreateText(sendForm, "sendPrompt", args, n);
XtManageChild(sendPrompt);
XmTextSetString(sendPrompt, "msg>");
// create the text input field
n = 0;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNleftWidget, sendPrompt); n++;
_sendText = XmCreateText(sendForm, "sendText", args, n);
XtManageChild(_sendText);
XtAddCallback(_sendText, XmNactivateCallback,
(XtCallbackProc)&ConfDoc::sendCB, (XtPointer)this);
// create the input label
n = 0;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, sendFrame); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
_inputLabel = XmCreateLabel(form, "inputLabel", args, n);
XtManageChild(_inputLabel);
// create the text output field
n = 0;
XtSetArg(args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
XtSetArg(args[n], XmNeditable, False); n++;
XtSetArg(args[n], XmNcursorPositionVisible, False); n++;
XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNtopWidget, outputLabel); n++;
XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
XtSetArg(args[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
XtSetArg(args[n], XmNbottomWidget, _inputLabel); n++;
_recvText = XmCreateScrolledText(form, "recvText", args, n);
XtManageChild(_recvText);
_recvConfText = new ConfText(_recvText, NULL);
// send all input from the keyboard to the text input field
XtSetKeyboardFocus(form, _sendText);
// initialize the group, user and help dialogs
_groupList.init(parent, "groups");
_userList.init(parent, "users");
_helpList.init(parent, "help");
return(form);
}
Boolean ConfDoc::setupChannel(char *buf)
{
// make sure a name was supplied
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No name supplied.");
return(FALSE);
}
// make sure the name's not too long
char user[30];
char *tmp = (char *)getWord(buf, 2);
if(strlen(tmp) > 30) {
_recvConfText->putStr("ERROR> Maximum name length is 30 characters.");
return(FALSE);
}
strcpy(user, tmp);
// check if user is logged in
if(!_userList.find(user)) {
char buf[MAX_BUF_SIZE];
strcpy(buf, "ERROR> user '");
strcat(buf, user);
strcat(buf, "' not logged in.");
_recvConfText->putStr(buf);
return(FALSE);
}
PrivateList* plist = new PrivateList();
plist->init(_sendText, "private", user, this);
plist->open();
}
Boolean ConfDoc::findUser(char *buf)
{
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No user name supplied.");
return(FALSE);
}
char fuser[30];
char* tmp = (char*)getWord(buf, 2);
if(strlen(tmp) > 30) {
_recvConfText->putStr("ERROR> Invalid user name.");
return(FALSE);
}
strcpy(fuser, tmp);
sendMsg(FIND, _user, _group, fuser);
sleep(1);
char tbuf[MAX_BUF_SIZE];
strcpy(tbuf, "INFO> User '");
strcat(tbuf, fuser);
if(!_userList.find(fuser)) {
strcat(tbuf, "' not logged in.");
_recvConfText->putStr(tbuf);
}
else {
strcat(tbuf, "' logged in.");
_recvConfText->putStr(tbuf);
}
return(TRUE);
}
Boolean ConfDoc::setGroup(char *buf)
{
if(numWords(buf) == 1) {
_groupList.open();
return(TRUE);
}
if(numWords(buf) > 1) {
char new_group[30];
char* tmp = (char*)getWord(buf, 2);
if(strlen(tmp) > 30) {
_recvConfText->putStr("ERROR> Maximum name length is 30 characters.");
return(FALSE);
}
strcpy(new_group, tmp);
if(numWords(buf) == 2) {
// add this group to the list.
sendMsg(LOGOUT, _user, _group, " ");
strcpy(_group, new_group);
// if it's a new group, add it to the list.
if(!_groupList.find(new_group)) {
_groupList.add(new_group, TRUE);
} else {
_groupList.select(new_group);
}
_userList.clear();
setInputLabel(new_group);
sendMsg(LOGIN, _user, _group, " ");
return(TRUE);
}
// send a message to the given group.
char data[256];
char *word;
strcpy(data, ""); // initialize local buffer
int n = 3;
while((word = getWord(buf, n++)) != NULL) {
strcat(data, word);
strcat(data, " ");
}
sendMsg(MESSAGE, _user, new_group, data);
}
return(TRUE);
}
Boolean ConfDoc::setName(char *buf)
{
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No name supplied.");
return(FALSE);
}
char *tmp;
char new_user[30];
char old_user[30];
tmp = (char *)getWord(buf, 2);
if(strlen(tmp) > 30) {
_recvConfText->putStr("ERROR> Maximum name length is 30 characters.");
return(FALSE);
}
strcpy(new_user, tmp);
// check if already used
if(_userList.find(new_user) > 0) {
char buf[MAX_BUF_SIZE];
strcpy(buf, "ERROR> user '");
strcat(buf, new_user);
strcat(buf, "' already logged in.");
_recvConfText->putStr(buf);
return(FALSE);
}
strcpy(old_user, _user);
strcpy(_user, new_user);
// send message to all servers, printing out the change you've made
if(!sendMsg(USER, new_user, _group, old_user)) {
_recvConfText->putStr("ERROR> sendMsg() failed.");
return(FALSE);
}
return(TRUE);
}
Boolean ConfDoc::sendMsg(short flags, char *user, char *group, char *data)
{
struct Message msg;
if(numWords(data) == 0) {
if(!((flags == LOGIN) || (flags == LOGOUT) || (flags == RING)))
return(FALSE);
}
msg.flags = flags;
strcpy(msg.user, user);
strcpy(msg.group, group);
if(msg.flags == USER) {
strcpy(msg.data, data);
}
else {
strcpy(msg.data, "(");
strcat(msg.data, _user);
strcat(msg.data, ".");
strcat(msg.data, _group);
strcat(msg.data, "): ");
strcat(msg.data, data);
}
int len = sizeof(msg) - sizeof(msg.data) + strlen(msg.data);
if(sendto(_socket, &msg, sizeof(msg), 0, &_sendAddr, _addrSize) < 0) {
perror("send");
return(FALSE);
}
bzero(msg.data, sizeof(msg.data)); // clear send buffer
return(TRUE);
}
Boolean ConfDoc::sendBroadcast(char *buf)
{
char *word;
char data[256];
int n = 2;
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No message supplied.");
return(FALSE);
}
strcpy(data, ""); // initialize local buffer
while((word = getWord(buf, n++)) != NULL) {
strcat(data, word);
strcat(data, " ");
}
if(!sendMsg(BROADCAST, _user, _group, data)) {
_recvConfText->putStr("ERROR> sendMsg() failed.");
return(FALSE);
}
return(TRUE);
}
Boolean ConfDoc::sendPrivate(char *buf, int ring)
{
int n = 3;
char user[30];
char data[256];
char *word;
if(ring) {
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No user supplied.");
return(FALSE);
}
}
else {
if(numWords(buf) <= 2) {
_recvConfText->putStr("ERROR> No user or message supplied.");
return(FALSE);
}
}
strcpy(user, getWord(buf, 2));
// check if user is logged in
if(!_userList.find(user)) {
char buf[MAX_BUF_SIZE];
strcpy(buf, "ERROR> user '");
strcat(buf, user);
strcat(buf, "' not logged in.");
_recvConfText->putStr(buf);
return(FALSE);
}
strcpy(data, ""); // initialize local buffer
while((word = getWord(buf, n++)) != NULL) {
strcat(data, word);
strcat(data, " ");
}
// echo the text locally (to keep track of what you've typed
char tdata[256];
strcpy(tdata, "TO> (");
strcat(tdata, user);
strcat(tdata, "): ");
strcat(tdata, data);
_recvConfText->putStr(tdata);
// this is a special case where we use the user field to represent
// the recipient, rather than the sender
if(ring) {
if(!sendMsg(RING, user, _group, data)) {
_recvConfText->putStr("ERROR> sendMsg() failed.");
return(FALSE);
}
}
else {
if(!sendMsg(PRIVATE, user, _group, data)) {
_recvConfText->putStr("ERROR> sendMsg() failed.");
return(FALSE);
}
}
return(TRUE);
}
Boolean ConfDoc::sendUrgent(char *buf)
{
char *word;
char data[256];
int n = 2;
if(numWords(buf) == 1) {
_recvConfText->putStr("ERROR> No message supplied.");
return(FALSE);
}
bzero(data, sizeof(data)); // initialize local buffer
while((word = getWord(buf, n++)) != NULL) {
strcat(data, word);
strcat(data, " ");
}
if(!sendMsg(URGENT, _user, _group, data)) {
_recvConfText->putStr("ERROR> sendMsg() failed.");
return(FALSE);
}
return(TRUE);
}
void ConfDoc::setInputLabel(char* label)
{
char labelText[64];
strcpy(labelText, "Input: (group=");
strcat(labelText, label);
strcat(labelText, ")");
XmString labelString = XmStringCreate(labelText, XmSTRING_DEFAULT_CHARSET);
Arg args[1];
XtSetArg(args[0], XmNlabelString, labelString);
XtSetValues(_inputLabel, args, 1);
}
int ConfDoc::numWords(char *buf)
{
int count = 0;
int end = 0;
while(!end) {
while(*buf == ' ') buf++;
if(*buf == '\0') return(count);
count++;
while(*buf != ' ') {
if(*buf == '\0') return(count);
buf++;
}
}
}
char *ConfDoc::getWord(char *buf, int pos)
{
static char word[256];
int n = 0;
int curpos = 0;
if(numWords(buf) < pos) return(NULL);
while(pos != curpos) {
while(*buf == ' ') buf++;
curpos++;
if(*buf == '\0') return(NULL);
while(*buf != ' ') {
if(*buf == '\0') {
curpos = pos;
break;
}
word[n++] = *buf++;
}
word[n] = '\0';
n = 0;
}
return(word);
}